﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
using System.Web;
using VemTransporte.Models.Basica;
using VemTransporte.Models.Persistencia;

namespace VemTransporte.Models.Negocio
{
    public class ControladorTotal
    {
        #region Atributos
        private RepUsuario rUsuario;
        private RepEndereco rEndereco;
        private RepEmpresa rEmpresa;
        private RepTipoTelefone rTipoTelefone;
        private RepEmpresaTelefone rEmpresaTelefone;
        private RepLinha rLinha;
        private RepVeiculo rVeiculo;
        private RepLocalizacao rLocalizacao;
        private RepHorario rHorario;
        private RepParada rParada;
        #endregion

        #region Construtor
        public ControladorTotal()
        {
            rUsuario = new RepUsuario();
            rEndereco = new RepEndereco();
            rEmpresa = new RepEmpresa();
            rTipoTelefone = new RepTipoTelefone();
            rEmpresaTelefone = new RepEmpresaTelefone();
            rLinha = new RepLinha();
            rVeiculo = new RepVeiculo();
            rLocalizacao = new RepLocalizacao();
            rHorario = new RepHorario();
            rParada = new RepParada();
        }
        #endregion

        #region Validações
        private void validarCamposUsuario(Usuario usuario)
        {
            if (usuario.Id == 0)
            {
                if (usuario.Nome == "")
                {
                    throw new Exception("Preenchar o campo nome!");
                }

                Regex letras = new Regex(@"^[0-9]+?(.|,[0-9]+)$");

                if (letras.IsMatch(usuario.Nome))
                {
                    throw new Exception("Nome Inválido!");
                }


                if (usuario.Senha.Length < 6 || usuario.Senha.Length > 8)
                {
                    throw new Exception("A senha deve ter no minimo 6 digitos e no máximo 8");
                }

                if (rUsuario.ProcurarUsuarioPorEMail(usuario.Email) != null)
                {
                    throw new Exception("O E-Mail já existe!");
                }

                Regex Ruso = new Regex(@"^[A-Za-z0-9](([_\.\-]?[a-zA-Z0-9]+)*)@([A-Za-z0-9]+)(([\.\-]?[a-zA-Z0-9]+)*)\.([A-Za-z]{2,})$");

                if (Ruso.IsMatch(usuario.Email))
                { }
                else
                {
                    throw new Exception("Email Inválido!");
                }
            }
        }

        private void validarCamposEmpresa(Empresa empresa)
        {

            if (empresa.Id == 0)
            {
                if (empresa.NomeFantasia == "")
                {
                    throw new Exception("Preenchar o campo nome fantasia!");
                }

                Regex letras = new Regex(@"^[0-9]+?(.|,[0-9]+)$");

                if (letras.IsMatch(empresa.NomeFantasia))
                {
                    throw new Exception("Nome Fantasia Inválido!");
                }
                if (empresa.NomeRazaoSocial == "")
                {
                    throw new Exception("Preenchar o campo razão social!");
                }

                if (empresa.LembreteSenha == "")
                {
                    throw new Exception("Preenchar o campo lembrete de senha!");
                }

                if (empresa.EmpresaTelefones == null)
                {
                    throw new Exception("É preciso preencher no minimo 1 telefone !");
                }

                if (empresa.Cnpj == "")
                {
                    throw new Exception("Preenchar o campo CNPJ!");
                }
                else
                {
                    if (!VerificaCnpj(empresa))
                        throw new Exception("CNPJ Inválido!");
                }

                //if (empresa.Endereco == null)
                //{
                    //throw new Exception("Preencher o campo CEP!");
                //}

                if (empresa.Senha.Length < 6 || empresa.Senha.Length > 8)
                {
                    throw new Exception("A senha deve ter no minimo 6 digitos e no máximo 8");
                }

                if ((empresa.Id == 0) && (rEmpresa.ProcurarEmpresaPorEMail(empresa.Email) != null))
                {
                    //Só válida se a empresa não existir!
                    throw new Exception("O E-Mail já existe!");
                }

                Regex rEmp = new Regex(@"^[A-Za-z0-9](([_\.\-]?[a-zA-Z0-9]+)*)@([A-Za-z0-9]+)(([\.\-]?[a-zA-Z0-9]+)*)\.([A-Za-z]{2,})$");

                if (rEmp.IsMatch(empresa.Email))
                { }
                else
                {
                    throw new Exception("Email Inválido!");
                }
            }
        }

        public static Boolean VerificaCnpj(Empresa emp)
        {
            Regex cnpjEx = new Regex(@"(^(\d{2}.\d{3}.\d{3}/\d{4}-\d{2})|(\d{14})$)");

            if (cnpjEx.IsMatch(emp.Cnpj))
            {
                return validacnpj(emp);
            }
            else
            {
                return false;
            }

        }

        //private static bool validaCnpj(Regex cnpj)
        //{
        //    throw new NotImplementedException();
        //}

        private static Boolean validacnpj(Empresa empcnpj)
        {

            int[] digitos, soma, resultado;

            int nrdig;

            string ftmt;

            string cnpj = empcnpj.Cnpj;

            Boolean[] cnpjok;

            cnpj = cnpj.Replace("/", "");

            cnpj = cnpj.Replace(".", "");

            cnpj = cnpj.Replace("-", "");

            if (cnpj == "00000000000000")
            {
                return false;
            }

            ftmt = "6543298765432";

            digitos = new int[14];

            soma = new int[2];

            soma[0] = 0;

            soma[1] = 0;

            resultado = new int[2];

            resultado[0] = 0;

            resultado[1] = 0;

            cnpjok = new Boolean[2];

            cnpjok[0] = false;

            cnpjok[1] = false;

            try
            {

                for (nrdig = 0; nrdig < 14; nrdig++)
                {

                    digitos[nrdig] = int.Parse(cnpj.Substring(nrdig, 1));

                    if (nrdig <= 11)

                        soma[0] += (digitos[nrdig] *

                        int.Parse(ftmt.Substring(nrdig + 1, 1)));

                    if (nrdig <= 12)

                        soma[1] += (digitos[nrdig] *

                        int.Parse(ftmt.Substring(nrdig, 1)));
                }

                for (nrdig = 0; nrdig < 2; nrdig++)
                {
                    resultado[nrdig] = (soma[nrdig] % 11);

                    if ((resultado[nrdig] == 0) || (resultado[nrdig] == 1))

                        cnpjok[nrdig] = (digitos[12 + nrdig] == 0);

                    else

                        cnpjok[nrdig] = (digitos[12 + nrdig] == (

                        11 - resultado[nrdig]));

                }

                empcnpj.Cnpj = cnpj;

                return (cnpjok[0] && cnpjok[1]);

            }

            catch
            {
                return false;
            }
        }

        private void validarLinha(Linha linha)
        {
            if (linha.Id == 0)
            {
                if (linha.Numero == "")
                {
                    throw new Exception("Preenchar o campo Numero!");
                }

                if (linha.Nome == "")
                {
                    throw new Exception("Preenchar o campo Nome!");
                }

                Regex letras = new Regex(@"^[aA-zZ]+((aA-zZ+)+)?$");

                if (letras.IsMatch(linha.Numero))
                {
                    throw new Exception("Preencha o campo numero da linha apenas com numeros!");
                }
            }
        }

        private void validarHora(Horario horario)
        {
            if (horario.Id == 0)
            {
                if (horario.HoraSaida == null || (horario.HoraChegada == null))
                {
                    throw new Exception("Preenchar o campo Horário de Saida, Horário chegada");
                }

                Regex numeros = new Regex(@"^([0-1][0-9]|[2][0-3]):([0-5][0-9])$");

            }
        }
               
   
        #endregion

        #region validar data



        #endregion

        #region Usuario
        public void Salvar(Usuario u)
        {
            this.validarCamposUsuario(u);

            if (u.Id == 0)
            {
                u.Senha = EncryptString(u.Senha);
            }

            rUsuario.Salvar(u);
        }

        public void Remover(Usuario u)
        {
            rUsuario.Excluir(u);
        }

        //Teste
        public Usuario ProcurarUsuarioPorId(int id)
        {
            
            return rUsuario.ProcurarPorId(id);
        }

        public Usuario ProcurarUsuarioPorEMail(string email)
        {
            return rUsuario.ProcurarUsuarioPorEMail(email);
        }

        public Usuario ProcurarUsuarioPorEmailESenha(string email, string senha)
        {
            Usuario retorno = null;

            retorno = rUsuario.ProcurarUsuarioPorEmailESenha(email, EncryptString(senha));

            if (retorno != null)
            {
                //retorno.Senha = DecryptString(retorno.Senha, "VemTransporteSecurity");
            }

            return retorno;
        }
        #endregion

        #region CEP

        public void Salvar(Endereco e)
        {
            rEndereco.Salvar(e);
        }

        public Endereco ProcurarEnderecoPorCep(string cep)
        {
            return rEndereco.ProcurarEnderecoPorCep(cep);
        }
        #endregion

        #region Empresa
        public void Salvar(Empresa e)
        {
            this.validarCamposEmpresa(e);

            if (e.Id == 0)
            {
                e.Senha = EncryptString(e.Senha);
            }

            rEmpresa.Salvar(e);
        }

        public void Alterar(Empresa e)
        {
            this.validarCamposEmpresa(e);

            rEmpresa.Alterar(e);

        }

        public Empresa ProcurarEmpresaPorEMailESenha(string email, string senha)
        {
            Empresa retorno = null;

            retorno = rEmpresa.ProcurarEmpresaPorEMailESenha(email, EncryptString(senha));

            if (retorno != null)
            {
                //retorno.Senha = DecryptString(retorno.Senha, "VemTransporteSecurity");
            }

            return retorno;
        }

        public IList<TipoTelefone> ProcurarTipoTelefoneTodos()
        {
            return rTipoTelefone.ProcurarTodos();
        }
        #endregion

        #region Parada
        public void Salvar(Parada p)
        {

            if (p.Id == 0)
            {
                if (ProcurarParadaPorNumero(p.Numero) != null)
                {
                    throw new Exception("O número da Parada já existe! Informe outro.");
                }

            }

            rParada.Salvar(p);

        }

        public Parada ProcurarParadaPorNumero(string numero)
        {
            return rParada.ProcurarParadaPorNumero(numero);
        }

        public IList<Parada> ProcurarParadaTodos()
        {
            return rParada.ProcurarTodos();
        }

        public void Remover(Parada p)
        {
            rParada.Excluir(p);
        }
        #endregion

        #region Horario
        public void Salvar(Horario h)
        {
            rHorario.Salvar(h);
        }

        public void Remover(Horario h)
        {
            rHorario.Excluir(h);
        }

        public Horario ProcurarHorarioPorId(int id)
        {
            return rHorario.ProcurarPorId(id);
        }

        public IList<Horario> ProcurarTodos()
        {
            return rHorario.ProcurarTodos();
        }
        #endregion

        #region Linha
        public void Salvar(Linha l)
        {
            this.validarLinha(l);

            if (l.Id == 0)
            {
                if (ProcurarLinhaPorNumero(l.Numero) != null)
                {
                    throw new Exception("O número da linha já existe! Informe outro.");
                }

                IList<Linha> linhas = ProcurarLinhaPorNome(l.Nome);

                if ((linhas != null) && (linhas.Count > 0))
                {
                    throw new Exception("O nome da linha já existe! Informe outro.");
                }
            }

            rLinha.Salvar(l);
        }

        public void Remover(Linha l)
        {
            rLinha.Excluir(l);
        }

        public Linha ProcurarLinhaPorId(int idLinha)
        {
            return rLinha.ProcurarPorId(idLinha);
        }


        public Linha ProcurarLinhaPorNumero(string numero)
        {
            return rLinha.ProcurarLinhaPorNumero(numero);
        }

        public IList<Linha> ProcurarLinhaPorNome(string nome)
        {
            return rLinha.ProcurarLinhaPorNome(nome);
        }

        public IList<Linha> ProcurarLinhaTodos()
        {
            return rLinha.ProcurarTodos();
        }



        #endregion

        #region Veiculo
        public void Salvar(Veiculo v)
        {
            if (v.Id == 0)
            {
                if (rVeiculo.ProcurarVeiculoPorPlaca(v.Placa) != null)
                {
                    throw new Exception("A placa já existe!");
                }/**/
            }

            rVeiculo.Salvar(v);
        }

        public void Remover(Veiculo v)
        {
            rVeiculo.Excluir(v);
        }

        public Veiculo ProcurarVeiculoPorId(int id)
        {
            return rVeiculo.ProcurarPorId(id);
        }

        public Veiculo ProcurarVeiculoPorPlaca(string placa)
        {
            return rVeiculo.ProcurarVeiculoPorPlaca(placa);
        }
        #endregion

        #region Localização
        public void Salvar(Localizacao l)
        {
            rLocalizacao.Salvar(l);
        }

        public Localizacao ProcurarUltimaLocalizacaoPorIdVeiculo(int id)
        {
            return rLocalizacao.ProcurarUltimaLocalizacaoPorIdVeiculo(id);
        }
        #endregion

        #region Utils
        public string EncryptString(string Message)
        {
            string Passphrase = "VemTransporteSecurity";
            byte[] Results;
            System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding();

            // Step 1. We hash the passphrase using MD5
            // We use the MD5 hash generator as the result is a 128 bit byte array
            // which is a valid length for the TripleDES encoder we use below

            MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider();
            byte[] TDESKey = HashProvider.ComputeHash(UTF8.GetBytes(Passphrase));

            // Step 2. Create a new TripleDESCryptoServiceProvider object
            TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider();

            // Step 3. Setup the encoder
            TDESAlgorithm.Key = TDESKey;
            TDESAlgorithm.Mode = CipherMode.ECB;
            TDESAlgorithm.Padding = PaddingMode.PKCS7;

            // Step 4. Convert the input string to a byte[]
            byte[] DataToEncrypt = UTF8.GetBytes(Message);

            // Step 5. Attempt to encrypt the string
            try
            {
                ICryptoTransform Encryptor = TDESAlgorithm.CreateEncryptor();
                Results = Encryptor.TransformFinalBlock(DataToEncrypt, 0, DataToEncrypt.Length);
            }
            finally
            {
                // Clear the TripleDes and Hashprovider services of any sensitive information
                TDESAlgorithm.Clear();
                HashProvider.Clear();
            }

            // Step 6. Return the encrypted string as a base64 encoded string
            return Convert.ToBase64String(Results);
        }

        public string DecryptString(string Message)
        {
            string Passphrase = "VemTransporteSecurity";
            byte[] Results;
            System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding();

            // Step 1. We hash the passphrase using MD5
            // We use the MD5 hash generator as the result is a 128 bit byte array
            // which is a valid length for the TripleDES encoder we use below

            MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider();
            byte[] TDESKey = HashProvider.ComputeHash(UTF8.GetBytes(Passphrase));

            // Step 2. Create a new TripleDESCryptoServiceProvider object
            TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider();

            // Step 3. Setup the decoder
            TDESAlgorithm.Key = TDESKey;
            TDESAlgorithm.Mode = CipherMode.ECB;
            TDESAlgorithm.Padding = PaddingMode.PKCS7;

            // Step 4. Convert the input string to a byte[]
            byte[] DataToDecrypt = Convert.FromBase64String(Message);

            // Step 5. Attempt to decrypt the string
            try
            {
                ICryptoTransform Decryptor = TDESAlgorithm.CreateDecryptor();
                Results = Decryptor.TransformFinalBlock(DataToDecrypt, 0, DataToDecrypt.Length);
            }
            finally
            {
                // Clear the TripleDes and Hashprovider services of any sensitive information
                TDESAlgorithm.Clear();
                HashProvider.Clear();
            }

            // Step 6. Return the decrypted string in UTF8 format
            return UTF8.GetString(Results);
        }
        #endregion

    }
}